package org.btik.light.server.dev.manage.type;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.btik.light.meta.DevMo;
import org.btik.light.meta.base.DevRpcServer;
import org.btik.light.meta.event.cmd.DefaultCmd;
import org.btik.light.server.dev.manage.ConnectHandler;
import org.btik.light.tool.type.StringUtil;
import org.btik.video.server.iface.DevChannel;
import org.springframework.beans.factory.InitializingBean;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;

import static org.btik.light.meta.LightDevAttrConstant.*;


/**
 * 摄像头设备连接回调
 *
 * @author lustre
 * @since 2023/3/8 12:40
 */

public class CamConnectHandler implements ConnectHandler, InitializingBean {
    private final Log log = LogFactory.getLog(CamConnectHandler.class);

    /**
     * 可用的通道索引
     */
    private static final LinkedList<Integer> CHANNEL_INDEX_QUEUE = new LinkedList<>();

    private static final HashMap<String, Integer> SN_CHANNEL_MAP = new HashMap<>(64);

    private DevRpcServer rpcServer;

    private DevChannel deviceChannel;

    private int videoChannelCount;


    @Override
    public void onConnect(DevMo devMo) {
        String sn = devMo.getSn();
        DefaultCmd defaultCmd = new DefaultCmd();
        defaultCmd.setTarget(sn);

        String setChannelIndex = devMo.getExtendedAttributes().get(SET_CAM_CHANNEL_INDEX_OP_CODE);
        if (StringUtil.isEmpty(setChannelIndex)) {
            rpcServer.sendError("prop of setCamChannelIndexOpCode not set");
            log.error("prop of setCamChannelIndexOpCode not set");
            return;
        }
        try {
            int opcode = Integer.parseInt(setChannelIndex);
            defaultCmd.setOpcode(opcode);
        }catch (Exception e){
            log.info(e);
            rpcServer.sendError("setCamChannelIndexOpCode must be numeric");
            return;
        }

        ArrayList<Object> params = new ArrayList<>();
        Integer index = getIndex(sn);

        log.info("sn:" + sn + ",index"  +index);
        if (index == null) {
            log.warn("These channels have been exhausted. ");
            return;
        }
        String indexStr = index.toString();
        devMo.setExtendedAttribute(CHANNEL_INDEX, indexStr);
        params.add(indexStr);
        defaultCmd.setParams(params);
        String type = devMo.getExtendedAttributes().get(ACCESS_CHANNEL_TYPE);
        rpcServer.sendCmd(defaultCmd, type);
        deviceChannel.attachMjpegVideoChannel(index, sn);

    }

    private Integer getIndex(String sn) {
        Integer index = SN_CHANNEL_MAP.get(sn);
        if (index == null) {
            index = CHANNEL_INDEX_QUEUE.poll();
            if (index == null) {
                return null;
            }
            SN_CHANNEL_MAP.put(sn, index);
        }
        return index;
    }

    @Override
    public void afterPropertiesSet() {
        for (int i = 0; i < videoChannelCount; i++) {
            CHANNEL_INDEX_QUEUE.add(i);
        }
    }

    public void setVideoChannelCount(int videoChannelCount) {
        this.videoChannelCount = videoChannelCount;
    }

    public void setRpcServer(DevRpcServer rpcServer) {
        this.rpcServer = rpcServer;
    }

    public void setDeviceChannel(DevChannel deviceChannel) {
        this.deviceChannel = deviceChannel;
    }


}
